#pragma once
#include <iostream>
#include <functional>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/epoll.h>
#include "connection.hh"
class tcp_reactor_t;

class epoller_t
{

public:
    epoller_t(const int timeout = -1, const size_t max_num = 128) : _max_num(max_num), _timeout(timeout), _ready_list(new epoll_event[max_num])

    {
        int fd_ret = epoll_create(1);
        if (fd_ret < 0)
        {
            exit(-1);
        }
        _epoll_fd = fd_ret;
    }
    ~epoller_t()
    {
        if (_epoll_fd >= 0)
            close(_epoll_fd);
        delete[] _ready_list;
    }
    // 增删读写关心
    bool add_care(connection_t &connection, uint32_t care)
    {
        epoll_event *p_event = connection.get_event();
        p_event->events |= care;
        return epoll_ctl(_epoll_fd, EPOLL_CTL_MOD, connection.get_fd(), p_event) == 0;
    }
    bool add_care(connection_t *p_connection, uint32_t care)
    {
        epoll_event *p_event = p_connection->get_event();
        p_event->events |= care;
        return epoll_ctl(_epoll_fd, EPOLL_CTL_MOD, p_connection->get_fd(), p_event) == 0;
    }
    bool del_care(connection_t &connection, uint32_t care)
    {
        epoll_event *p_event = connection.get_event();
        p_event->events &= care ^ (uint32_t(~0));
        return epoll_ctl(_epoll_fd, EPOLL_CTL_MOD, connection.get_fd(), p_event) == 0;
    }
    bool del_care(connection_t *p_connection, uint32_t care)
    {
        epoll_event *p_event = p_connection->get_event();
        p_event->events &= care ^ (uint32_t(~0));
        return epoll_ctl(_epoll_fd, EPOLL_CTL_MOD, p_connection->get_fd(), p_event) == 0;
    }
    // 把封装后的连接添加到epoll模型
    bool add_connection(connection_t &connection)
    {
        return epoll_ctl(_epoll_fd, EPOLL_CTL_ADD, connection.get_fd(), connection.get_event()) == 0;
    }
    bool add_connection(connection_t *p_connection)
    {
        return epoll_ctl(_epoll_fd, EPOLL_CTL_ADD, p_connection->get_fd(), p_connection->get_event()) == 0;
    }
    // 删除连接
    bool del_connection(connection_t &connection)
    {
        return epoll_ctl(_epoll_fd, EPOLL_CTL_DEL, connection.get_fd(), nullptr) == 0;
    }
    bool del_connection(connection_t *p_connection)
    {
        return epoll_ctl(_epoll_fd, EPOLL_CTL_DEL, p_connection->get_fd(), nullptr) == 0;
    }
    int wait()
    {
        // 返回就绪个数 阻塞等待
        return _cur_list_len = epoll_wait(_epoll_fd, _ready_list, _max_num, _timeout);
    }
    epoll_event *get_event_by_index(int index)
    {
        if (index < 0 || index >= _cur_list_len)
            return nullptr;
        return _ready_list + index;
    }

private:
    size_t _epoll_fd;
    size_t _max_num;
    int _timeout;
    // 就绪队列
    epoll_event *_ready_list;
    size_t _cur_list_len = 0;
};
using handler_t = std::function<bool(connection_t &)>;
